package checkers3d.logic;

import checkers3d.presentation.GUIButton;
import checkers3d.presentation.GUIContainer;
import checkers3d.presentation.GUILabel;
import checkers3d.presentation.GUIPictureBox;
import checkers3d.presentation.GUITextbox;
import checkers3d.presentation.GameEngine;
import checkers3d.presentation.IDrawable;
import checkers3d.presentation.IInputObserver;
import checkers3d.presentation.UtilGUI;
import checkers3d.storage.DataManagerAccounts;
import java.awt.Color;
import java.awt.Point;
import java.util.LinkedList;

/**
 * Allows for two players to login and start playing a scenario.
 *
 * @author Ruben Acuna
 */
public class WindowLoginMP extends GUIContainer
{
    /**
     * Y axis value along which buttons will be centered.
     */
    private final int CONTROL_BUTTON_AXIS = GameEngine.WINDOW_SIZE.y - 100;

    /**
     * Reference the login button that the player clicks to start.
     */
    GUIButton buttonLogin;

    /**
     * Current observer for the login button.
     */
    IInputObserverLogin loginObserver;

    /**
     * GUI component for getting homes name.
     */
    GUITextbox loginHomeName;

    /**
     * GUI component for getting the homes password.
     */
    GUITextbox loginHomePassword;

    /**
     * GUI component that displays the homes validation state as a color.
     */
    GUILabel loginHomeValidation;

    /**
     * GUI component for getting visitors name.
     */
    GUITextbox loginVisitorName;

    /**
     * GUI component for getting the visitors password.
     */
    GUITextbox loginVisitorPassword;

    /**
     * GUI component that displays the visitors validation state as a color.
     */
    GUILabel loginVisitorValidation;

    public WindowLoginMP(Point size)
    {
        super(size);

        LinkedList<IDrawable> buttons = new LinkedList<IDrawable>();

        //add background image.
        add(new GUIPictureBox("Background.png", new Point()));

        //create the start button with behavior. ObserverReturn is to prevent crashing.
        buttonLogin = new GUIButton("button-start.png", null, new ObserverReturn());
        buttons.add(buttonLogin);

        //create the return button with behavior.
        buttons.add(new GUIButton("button-return.png", null, new ObserverReturn()));

        int xOffset = 100;
        //add labels
        add(new GUILabel("Home Login", Color.WHITE, new Point(191 + xOffset, 250)));
        add(new GUILabel("Name:", Color.WHITE, new Point(124 + xOffset, 302)));
        add(new GUILabel("Password:", Color.WHITE, new Point(102 + xOffset, 322)));
        loginHomeValidation = new GUILabel("Ready", Color.RED, new Point(207 + xOffset, 270));
        add(loginHomeValidation);
        add(new GUILabel("Visitor Login", Color.WHITE, new Point(191 + 352 + xOffset, 250)));
        add(new GUILabel("Name:", Color.WHITE, new Point(124 + 352 + xOffset, 302)));
        add(new GUILabel("Password:", Color.WHITE, new Point(102 + 352 + xOffset, 322)));
        loginVisitorValidation = new GUILabel("Ready", Color.RED, new Point(207 + 352 + xOffset, 270));
        add(loginVisitorValidation);

        //add the textbox for both players name and password.
        loginHomeName = new GUITextbox(new Point(166 + xOffset, 300), 25, this);
        loginHomePassword = new GUITextbox(new Point(166 + xOffset, 320), 25, this);
        loginHomePassword.setSecure(true);
        loginVisitorName = new GUITextbox(new Point(166 + 352 + xOffset, 300), 25, this);
        loginVisitorPassword = new GUITextbox(new Point(166 + 352 + xOffset, 320), 25, this);
        loginVisitorPassword.setSecure(true);

        //add the buttons to the GUIContainer.
        for(IDrawable component : buttons)
            add(component);

        //compute the positions of the buttons
        UtilGUI.computeLayoutSpanning(getSize(), CONTROL_BUTTON_AXIS, buttons);
    }

    /**
     * Updates the validation state embedded in the color of the ready label.
     */
    private void validatePlayers()
    {
        loginHomeValidation.setColor(Color.RED);
        loginVisitorValidation.setColor(Color.RED);
        try
        {
            String homeName = loginHomeName.getText();
            String homePassword = loginHomePassword.getText();
            String visitorName = loginVisitorName.getText();
            String visitorPassword = loginVisitorPassword.getText();

            if(DataManagerAccounts.doesPlayerExist(homeName))
                if(DataManagerAccounts.getPlayerPassword(homeName).equals(homePassword))
                    if(!homeName.equals(visitorName))
                        loginHomeValidation.setColor(Color.GREEN);

            if(DataManagerAccounts.doesPlayerExist(visitorName))
                if(DataManagerAccounts.getPlayerPassword(visitorName).equals(visitorPassword))
                    if(!homeName.equals(visitorName))
                        loginVisitorValidation.setColor(Color.GREEN);
        }
        catch(Exception error)
        {
            loginHomeValidation.setColor(Color.RED);
            loginVisitorValidation.setColor(Color.RED);
        }
    }

    /**
     * Sets the current observer of the login button.
     *
     * @param observer A IInputObject for the login button.
     */
    public void setLoginObserver(IInputObserverLogin observer)
    {
        loginObserver = observer;
    }
    
    /**
     * Handles a key press, when the GUIContainer is in focus, by sending it to
     * all of its components. If both players are validated, the start button is
     * enabled.
     *
     * @param  key       The character of the key that was pressed.
     */
    @Override
    public void onKeyPress(char key)
    {
        super.onKeyPress(key);

        validatePlayers();

        if(loginHomeValidation.getColor() == Color.GREEN
           && loginVisitorValidation.getColor() == Color.GREEN)
        {
            Player home = DataManagerAccounts.loadPlayer(loginHomeName.getText());
            Player visitor = DataManagerAccounts.loadPlayer(loginVisitorName.getText());

            loginObserver.setHome(home);
            loginObserver.setVisitor(visitor);

            buttonLogin.setObserver(loginObserver);
        }
        else
        {
            buttonLogin.setObserver(new ObserverNull());
        }
    }

    /**
     * Returns a string representation of this object containing it's class name.
     *
     * @return String representation.
     */
    @Override
    public String toString()
    {
        return getClass().getName();
    }

    /**
     * A observer for a button that returns user to the scenario select screen.
     */
    private class ObserverReturn implements IInputObserver
    {
        /**
         * Returns the user to the scenario select screen.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            GameMaster.getInstance().removeTopGUIContainer();
        }

         /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * A observer for a button that does nothing.
     */
    private class ObserverNull implements IInputObserver
    {
        /**
         * Does nothing when a click happens.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //do nothing.
        }

         /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    public interface IInputObserverLogin extends IInputObserver
    {
        void setHome(Player player);

        void setVisitor(Player home);
    }
}